#include "EconomyShop.h"
#include "EconomyPlugin.h"
#include "Managers/GameManager.h"
#include <fstream>
#include "spdlog/fmt/fmt.h"

#include "Expand/Plugins/AuthPlugin.h"
#include "Expand/PluginsManager.h"

#include "Network/Client.h"
#include "EconomyAPI.h"
#include "Player/PlayerData.h"
#include "Components/ComponentPlayer.h"
#include "Components/ComponentBody.h"

namespace Economy
{
    static const std::string titleText = "商店";
    constexpr const char *help1 = "\n"
                "/shop    -查看商店有关的指令\n"
                "/shop edit    -开启或关闭商店牌子编辑\n"
                "/shop shell (物品id) (数量) (价格)    -创造回收商店\n"
                "/shop shop (物品id) (数量) (价格)    -创造商店";

    static const std::string normalHelp = help1;


    EconomyShop::~EconomyShop() {}

    void EconomyShop::load()
    {
        m_economyAPI = GameSingleton::singletonPtr->getSingleton<EconomyAPI>();
        m_authPlugin = GameSingleton::pluginsManager->findPlugin<AuthPlugin>();

        std::ifstream stream;
        stream.open(fmt::format("{}/EconomyShop.json", EconomyPlugin::PluginDataDirectory));

        if (stream.is_open())
        {
            nlohmann::json jsonData;
            stream >> jsonData;
            Utils::GetJsonValue<std::map<std::string, std::vector<ShopData>>>(jsonData, m_shopMap, "data", std::map<std::string, std::vector<ShopData>>());
        }
        
        stream.close();
    }

    void EconomyShop::save()
    {
        m_shopMapMutex.lock();

        nlohmann::json jsonData = 
        {
            { "data", m_shopMap }
        };
        Utils::SaveTextFile(fmt::format("{}/EconomyShop.json", EconomyPlugin::PluginDataDirectory), jsonData.dump());

        m_shopMapMutex.unlock();
    }


    ShopData *EconomyShop::getShopData(const Point3 &point)
    {
        int32_t regionX = (point.posX >> 8);
        int32_t regionY = (point.posZ >> 8);
        Point3 targetPoint((point.posX & 0xFF), (point.posY & 0xFF), (point.posZ & 0xFF));

        std::string key = fmt::format("{},{}", regionX, regionY);
        std::lock_guard<std::mutex> lk(m_shopMapMutex);

        auto it = m_shopMap.find(key);
        if (it != m_shopMap.end())
        {
            for (ShopData &shopData : it->second)
            {
                if (shopData.point == targetPoint)
                {
                    return &shopData;
                }
            }
        }
        return nullptr;
    }

    bool EconomyShop::addShop(const ShopData &shopData)
    {
        Point3 point = shopData.point;
        int32_t regionX = (point.posX >> 8);
        int32_t regionY = (point.posZ >> 8);
        Point3 targetPoint((point.posX & 0xFF), (point.posY & 0xFF), (point.posZ & 0xFF));

        std::string key = fmt::format("{},{}", regionX, regionY);

        ShopData newShopData;
        newShopData.point = targetPoint;
        newShopData.value = shopData.value;
        newShopData.count = shopData.count;
        newShopData.price = shopData.price;
        newShopData.shopType = shopData.shopType;

        std::lock_guard<std::mutex> lk(m_shopMapMutex);

        auto it = m_shopMap.find(key);
        if (it != m_shopMap.end())
        {
            it->second.push_back(newShopData);
        }
        else
        {
            m_shopMap[key] = std::vector<ShopData>{ newShopData };
        }
        return true;
    }

    bool EconomyShop::removeShop(const Point3 &point)
    {
        int32_t regionX = (point.posX >> 8);
        int32_t regionY = (point.posZ >> 8);
        Point3 targetPoint((point.posX & 0xFF), (point.posY & 0xFF), (point.posZ & 0xFF));

        std::string key = fmt::format("{},{}", regionX, regionY);
        std::lock_guard<std::mutex> lk(m_shopMapMutex);

        auto it = m_shopMap.find(key);
        if (it != m_shopMap.end())
        {
            for (auto shopIt = it->second.begin(); shopIt != it->second.end(); ++shopIt)
            {
                if (shopIt->point == targetPoint)
                {
                    it->second.erase(shopIt);
                    return true;
                }
            }
        }
        return false;
    }

    void EconomyShop::processCmd(IPlugin::ChatObj &chatObj, std::vector<std::string> &cmdDataVec)
    {
        if(chatObj.m_isTerminal == true)
        {
            chatObj.sendMessage(titleText, "控制台不能使用该指令");
            return;
        }
        if(cmdDataVec.size() == 2)
        {
            if (cmdDataVec[1] == "edit")
            {
                m_createShopMutex.lock();
                auto it = m_editPlayer.find(chatObj.m_client->guid);
                if (it != m_editPlayer.end())
                {
                    m_editPlayer.erase(it);
                    chatObj.sendMessage(titleText, "关闭商店牌子信息编辑");
                }
                else
                {
                    m_editPlayer.insert(chatObj.m_client->guid);
                    chatObj.sendMessage(titleText, "开启商店牌子信息编辑");
                }
                m_createShopMutex.unlock();

                return;
            }
        }
        else if(cmdDataVec.size() >= 5)
        {
            if (cmdDataVec[1] == "shell")
            {
                ShopData shopData;
                shopData.value = atoi(cmdDataVec[2].c_str());
                shopData.count = atoi(cmdDataVec[2].c_str());
                shopData.price = atoi(cmdDataVec[2].c_str());
                shopData.shopType = ShopType::Shell;

                m_createShopMutex.lock();
                m_createShopPlayer[chatObj.m_client->guid] = shopData;
                m_createShopMutex.unlock();

                chatObj.sendMessage(titleText, "放置铁牌子创造回收商店");
            }
            else if (cmdDataVec[1] == "shop")
            {
                ShopData shopData;
                shopData.value = atoi(cmdDataVec[2].c_str());
                shopData.count = atoi(cmdDataVec[2].c_str());
                shopData.price = atoi(cmdDataVec[2].c_str());
                shopData.shopType = ShopType::Shop;

                m_createShopMutex.lock();
                m_createShopPlayer[chatObj.m_client->guid] = shopData;
                m_createShopMutex.unlock();

                chatObj.sendMessage(titleText, "放置铁牌子创造商店");
            }
        }
        chatObj.sendMessage(titleText, normalHelp);
    }

}
